#ifndef __VMM_H__
#define __VMM_H__
#include "shyper_service.h"

typedef unsigned long usize;
typedef int i32;

#define NAME_MAX_LEN (32)
#define VM_MEM_REGION_MAX (4)
#define PASSTHROUGH_DEV_MAX_NUM (128)
#define EMULATED_DEV_MAX_NUM (16)
#define DEV_MAX_NUM (PASSTHROUGH_DEV_MAX_NUM + EMULATED_DEV_MAX_NUM)

#define CFG_MAX_NUM (0x10)
#define IRQ_MAX_NUM (0x40)

enum vm_state {
    VM_S_INV,
    VM_S_PENDING,
    VM_S_ACTIVE,
};

enum vm_type {
    VM_T_OS,
    VM_T_BMA,
};

enum emu_device_type {
    EMU_DEVICE_T_CONSOLE,
    EMU_DEVICE_T_GICD,
    EMU_DEVICE_T_VIRTIO_BLK,
    EMU_DEVICE_T_VIRTIO_NET,
};

struct vm_info {
    int id;
    char vm_name[NAME_MAX_LEN];
    enum vm_type type;
    enum vm_state state;
};

struct vm_emulated_device_config {
    char name[NAME_MAX_LEN];
    usize base_ipa;
    usize length;
    usize irq_id;
    usize cfg_num;
    usize cfg_list[CFG_MAX_NUM];
    enum emu_device_type type;
};

struct vm_passthrough_device_config {
    char name[NAME_MAX_LEN];
    usize base_pa;
    usize base_ipa;
    usize length;
    bool dma;
    usize smmu_id;
    usize irq_num;
    usize irq_list[IRQ_MAX_NUM];
};

struct vm_image_config {
    char kernel_filename[NAME_MAX_LEN];
    usize kernel_load_ipa;
    usize kernel_entry_point;
    char device_tree_filename[NAME_MAX_LEN];
    usize device_tree_load_ipa;
    char ramdisk_filename[NAME_MAX_LEN];
    usize ramdisk_load_ipa;
};

struct vm_cpu_config {
    usize num;
    u32 allocate_bitmap;
    i32 master;
};

struct vm_memory_config {
    u32 num;
    struct {
        u64 ipa_start;
        u64 length;
    } region[VM_MEM_REGION_MAX];
};

struct vm_config_entry {
    char name[NAME_MAX_LEN];
    enum vm_type type;
    struct vm_memory_config memory;
    struct vm_image_config image;
    struct vm_cpu_config cpu;
    usize emulated_device_num;
    struct vm_emulated_device_config emulated_device[EMULATED_DEV_MAX_NUM];
    usize passthrough_device_num;
    struct vm_passthrough_device_config
        passthrough_device[PASSTHROUGH_DEV_MAX_NUM];
};

// void list_vm_info(void *arg);
// void display_vm_def_cfg(struct vm_config_entry *cfg);
#endif